package com.neo.code.lucene.demo01;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.IOException;

/**
 * @author baiyp
 */
public class Searcher {
    IndexSearcher indexSearcher;
    QueryParser queryParser;

    public Searcher(String indexDirectoryPath) throws IOException {
        Directory indexDirectory = FSDirectory.open(new File(indexDirectoryPath));
        indexSearcher = new IndexSearcher(indexDirectory);
        queryParser = new QueryParser(Version.LUCENE_36, Constants.CONTENTS,
                new StandardAnalyzer(Version.LUCENE_36));
    }

    public TopDocs search(String searchQuery) throws IOException, ParseException {
        Query query = queryParser.parse(searchQuery);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingTermQuery(String searchQuery) throws IOException {
        Term term = new Term(Constants.CONTENTS, searchQuery);
        Query query = new TermQuery(term);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingTermRangeQuery(String searchQueryMin, String searchQueryMax) throws IOException {
        Query query = new TermRangeQuery(Constants.FILE_LENGTH,
                searchQueryMin, searchQueryMax, true, true);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingPrefixQuery(String searchQuery) throws IOException {
        Term term = new Term(Constants.FILE_NAME, searchQuery);
        Query query = new PrefixQuery(term);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingBooleanQuery(String searchQuery1, String searchQuery2) throws IOException {
        Term term1 = new Term(Constants.FILE_NAME, searchQuery1);
        Query query1 = new TermQuery(term1);
        Term term2 = new Term(Constants.FILE_NAME, searchQuery2);
        Query query2 = new PrefixQuery(term2);
        BooleanQuery query = new BooleanQuery();
        query.add(query1, BooleanClause.Occur.MUST_NOT);
        query.add(query2, BooleanClause.Occur.MUST);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingPhraseQuery(String... phrases) throws IOException {
        PhraseQuery query = new PhraseQuery();
        query.setSlop(2);
        for (String word : phrases) {
            query.add(new Term(Constants.CONTENTS, word));
        }
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingWildCardQuery(String searchQuery) throws IOException {
        Term term = new Term(Constants.FILE_NAME, searchQuery);
        Query query = new WildcardQuery(term);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingFuzzyQuery(String searchQuery) throws IOException {
        Term term = new Term(Constants.FILE_NAME, searchQuery);
        Query query = new FuzzyQuery(term, 0.5f);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs searchUsingMatchAllDocsQuery(String searchQuery) throws IOException {
        Query query = new MatchAllDocsQuery(searchQuery);
        return indexSearcher.search(query, Constants.MAX_SEARCH);
    }

    public TopDocs sortUsingRelevance(String searchQuery) throws IOException {
        Term term = new Term(Constants.FILE_NAME, searchQuery);
        Query query = new WildcardQuery(term);
        indexSearcher.setDefaultFieldSortScoring(true, false);
        return indexSearcher.search(query, Constants.MAX_SEARCH, Sort.RELEVANCE);
    }

    public TopDocs sortUsingIndex(String searchQuery) throws IOException {
        Term term = new Term(Constants.FILE_NAME, searchQuery);
        Query query = new WildcardQuery(term);
        indexSearcher.setDefaultFieldSortScoring(true, false);
        return indexSearcher.search(query, Constants.MAX_SEARCH, Sort.INDEXORDER);
    }

    public TopDocs sortUsingCustom(String searchQuery) throws IOException {
        Term term = new Term(Constants.FILE_NAME, searchQuery);
        Query query = new WildcardQuery(term);
        indexSearcher.setDefaultFieldSortScoring(true, false);
        return indexSearcher.search(query, Constants.MAX_SEARCH, new Sort(new SortField(Constants.FILE_LENGTH, SortField.INT, true)));
    }

    public Document getDocument(ScoreDoc scoreDoc) throws CorruptIndexException, IOException {
        return indexSearcher.doc(scoreDoc.doc);
    }

    public void close() throws IOException {
        indexSearcher.close();
    }
}
